home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Programming / Wipeout / source / filter.c < prev    next >
C/C++ Source or Header  |  1998-04-12  |  7KB  |  402 lines

  1. /*
  2.  * $Id: filter.c 1.4 1998/04/12 18:06:58 olsen Exp olsen $
  3.  *
  4.  * :ts=4
  5.  *
  6.  * Wipeout -- Traces and munges memory and detects memory trashing
  7.  *
  8.  * Written by Olaf `Olsen' Barthel <olsen@sourcery.han.de>
  9.  * Public Domain
  10.  */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "global.h"
  14. #endif    /* _GLOBAL_H */
  15.  
  16. /******************************************************************************/
  17.  
  18. STATIC struct MinList    ForbidList;
  19. STATIC struct MinList    PermitList;
  20. STATIC BOOL                ListsInitialized;
  21. STATIC BOOL                ForbidAll;
  22. STATIC BOOL                PermitAll;
  23.  
  24. /******************************************************************************/
  25.  
  26. STATIC VOID
  27. ClearList(struct MinList * list)
  28. {
  29.     struct MinNode * node;
  30.     struct MinNode * next;
  31.  
  32.     /* return the contents of a list to the
  33.      * public memory list.
  34.      */
  35.     for(node = list->mlh_Head ;
  36.        (next = node->mln_Succ) != NULL ;
  37.         node = next)
  38.     {
  39.         PrivateFreeVec(node);
  40.     }
  41.  
  42.     /* leave an empty list behind */
  43.     NewList((struct List *)list);
  44. }
  45.  
  46. STATIC VOID
  47. MoveList(struct MinList * source,struct MinList * destination)
  48. {
  49.     struct MinNode * node;
  50.     struct MinNode * next;
  51.  
  52.     /* move the contents of one list to another */
  53.     for(node = source->mlh_Head ;
  54.        (next = node->mln_Succ) != NULL ;
  55.         node = next)
  56.     {
  57.         AddTail((struct List *)destination,(struct Node *)node);
  58.     }
  59.  
  60.     /* leave an empty source list behind */
  61.     NewList((struct List *)source);
  62. }
  63.  
  64. /******************************************************************************/
  65.  
  66. VOID
  67. ClearFilterList(VOID)
  68. {
  69.     /* clear both filter lists, but only if they
  70.      * have been initialized before.
  71.      */
  72.     if(ListsInitialized)
  73.     {
  74.         ClearList(&ForbidList);
  75.         ClearList(&PermitList);
  76.     }
  77. }
  78.  
  79. VOID
  80. InitFilterList(VOID)
  81. {
  82.     /* initialize the filter lists and assume
  83.      * defaults (track all memory allocations)
  84.      */
  85.     if(NOT ListsInitialized)
  86.     {
  87.         NewList((struct List *)&ForbidList);
  88.         NewList((struct List *)&PermitList);
  89.  
  90.         ListsInitialized = TRUE;
  91.  
  92.         ForbidAll = FALSE;
  93.         PermitAll = TRUE;
  94.     }
  95. }
  96.  
  97. /******************************************************************************/
  98.  
  99. STATIC BOOL
  100. GetNextName(
  101.     STRPTR *    keyPtr,
  102.     STRPTR        name,
  103.     LONG        nameLen)
  104. {
  105.     STRPTR start;
  106.     STRPTR stop;
  107.     BOOL result = FALSE;
  108.  
  109.     /* scan the "key" string for the next following name;
  110.      * names are separated by "|" characters
  111.      */
  112.  
  113.     ASSERT(keyPtr != NULL && name != NULL && nameLen > 0);
  114.  
  115.     start = (*keyPtr);
  116.     while((*start) != '\0' && (*start) == '|')
  117.         start++;
  118.  
  119.     stop = start;
  120.  
  121.     while((*stop) != '\0')
  122.     {
  123.         if((*stop) == '\\')
  124.         {
  125.             if(stop[1] != '\0')
  126.             {
  127.                 stop += 2;
  128.             }
  129.             else
  130.             {
  131.                 break;
  132.             }
  133.         }
  134.         else
  135.         {
  136.             if((*stop) == '|')
  137.             {
  138.                 break;
  139.             }
  140.             else
  141.             {
  142.                 stop++;
  143.             }
  144.         }
  145.     }
  146.  
  147.     if(start != stop)
  148.     {
  149.         LONG keyLen = (LONG)stop - (LONG)start + 1;
  150.         LONG len;
  151.         LONG i;
  152.  
  153.         len = 0;
  154.  
  155.         for(i = 0 ; i < keyLen ; i++)
  156.         {
  157.             if(start[i] == '|' || len == nameLen)
  158.                 break;
  159.  
  160.             if(start[i] == '\\')
  161.             {
  162.                 name[len++] = start[++i];
  163.             }
  164.             else
  165.             {
  166.                 name[len++] = start[i];
  167.             }
  168.         }
  169.  
  170.         name[len] = '\0';
  171.  
  172.         if((*stop) == '|')
  173.         {
  174.             (*keyPtr) = stop+1;
  175.         }
  176.         else
  177.         {
  178.             (*keyPtr) = stop;
  179.         }
  180.  
  181.         result = TRUE;
  182.     }
  183.  
  184.     /* return TRUE if there is another name to follow,
  185.      * FALSE otherwise (= finished processing the key
  186.      * string)
  187.      */
  188.  
  189.     return(result);
  190. }
  191.  
  192. /******************************************************************************/
  193.  
  194. BOOL
  195. UpdateFilter(const STRPTR filterString)
  196. {
  197.     STRPTR string = (STRPTR)filterString;
  198.     struct MinList forbidList;
  199.     struct MinList permitList;
  200.     UBYTE taskName[MAX_FILENAME_LEN];
  201.     STRPTR name;
  202.     BOOL forbidAll;
  203.     BOOL permitAll;
  204.     BOOL success = TRUE;
  205.  
  206.     /* assume defaults */
  207.     NewList((struct List *)&forbidList);
  208.     NewList((struct List *)&permitList);
  209.  
  210.     forbidAll = FALSE;
  211.     permitAll = TRUE;
  212.  
  213.     /* process the filter string */
  214.     while(GetNextName(&string,taskName,sizeof(taskName)))
  215.     {
  216.         /* exclude a name from the list? */
  217.         if(taskName[0] == '!')
  218.         {
  219.             name = &taskName[1];
  220.  
  221.             /* "ALL" means that no allocation should be
  222.              * excluded from being watched
  223.              */
  224.             if(Stricmp(name,"ALL") == SAME)
  225.             {
  226.                 forbidAll = TRUE;
  227.  
  228.                 ClearList(&forbidList);
  229.             }
  230.             else
  231.             {
  232.                 struct Node * node;
  233.  
  234.                 /* remember the name of the task whose name
  235.                  * should be used in the exclusion list
  236.                  */
  237.                 node = PrivateAllocVec(sizeof(*node) + strlen(name)+1,MEMF_ANY);
  238.                 if(node != NULL)
  239.                 {
  240.                     node->ln_Name = (char *)(node + 1);
  241.  
  242.                     strcpy(node->ln_Name,name);
  243.                     AddTail((struct List *)&forbidList,node);
  244.  
  245.                     forbidAll = FALSE;
  246.                 }
  247.                 else
  248.                 {
  249.                     success = FAILURE;
  250.                     break;
  251.                 }
  252.             }
  253.         }
  254.         else
  255.         {
  256.             name = taskName;
  257.  
  258.             /* "ALL" means that all allocations should be
  259.              * watched
  260.              */
  261.             if(Stricmp(name,"ALL") == SAME)
  262.             {
  263.                 permitAll = TRUE;
  264.  
  265.                 ClearList(&permitList);
  266.             }
  267.             else
  268.             {
  269.                 struct Node * node;
  270.  
  271.                 /* remember the name of the task whose name
  272.                  * should be used in the inclusion list
  273.                  */
  274.                 node = PrivateAllocVec(sizeof(*node) + strlen(name)+1,MEMF_ANY);
  275.                 if(node != NULL)
  276.                 {
  277.                     node->ln_Name = (char *)(node + 1);
  278.  
  279.                     strcpy(node->ln_Name,name);
  280.                     AddTail((struct List *)&permitList,node);
  281.  
  282.                     permitAll = FALSE;
  283.                 }
  284.                 else
  285.                 {
  286.                     success = FAILURE;
  287.                     break;
  288.                 }
  289.             }
  290.         }
  291.     }
  292.  
  293.     /* did we succeed in splitting the filter string
  294.      * into list nodes?
  295.      */
  296.     if(success)
  297.     {
  298.         Forbid();
  299.  
  300.         /* get rid of all the old filter list entries */
  301.         ClearList(&ForbidList);
  302.         ClearList(&PermitList);
  303.  
  304.         /* use the new list entries */
  305.         MoveList(&forbidList,&ForbidList);
  306.         MoveList(&permitList,&PermitList);
  307.  
  308.         /* and the new options */
  309.         ForbidAll = forbidAll;
  310.         PermitAll = permitAll;
  311.  
  312.         Permit();
  313.     }
  314.     else
  315.     {
  316.         ClearList(&forbidList);
  317.         ClearList(&permitList);
  318.     }
  319.  
  320.     return(success);
  321. }
  322.  
  323. /******************************************************************************/
  324.  
  325. BOOL
  326. CanAllocate(VOID)
  327. {
  328.     BOOL result = TRUE;
  329.  
  330.     /* check whether the current task should be allowed to
  331.      * make a memory allocation to be watched
  332.      */
  333.     if(GetTaskName(NULL,GlobalNameBuffer,sizeof(GlobalNameBuffer)))
  334.     {
  335.         if(ForbidAll)
  336.         {
  337.             /* should the allocations not be watched? */
  338.             if(CANNOT FindIName((struct List *)&PermitList,GlobalNameBuffer))
  339.                 result = FALSE;
  340.         }
  341.         else if (PermitAll)
  342.         {
  343.             /* should the allocations not be watched? */
  344.             if(FindIName((struct List *)&ForbidList,GlobalNameBuffer))
  345.                 result = FALSE;
  346.         }
  347.         else
  348.         {
  349.             result = FALSE;
  350.  
  351.             /* should the allocations be watched? */
  352.             if(       FindIName((struct List *)&PermitList,GlobalNameBuffer) &&
  353.                CANNOT FindIName((struct List *)&ForbidList,GlobalNameBuffer))
  354.             {
  355.                 result = TRUE;
  356.             }
  357.         }
  358.     }
  359.  
  360.     return(result);
  361. }
  362.  
  363. /******************************************************************************/
  364.  
  365. VOID
  366. CheckFilter(VOID)
  367. {
  368.     /* print the contents of the two watch lists */
  369.  
  370.     Forbid();
  371.  
  372.     if(NOT IsListEmpty((struct List *)&PermitList))
  373.     {
  374.         struct Node * node;
  375.  
  376.         DPrintf("\nMemory allocations done by the following task(s) are being watched:\n");
  377.  
  378.         for(node = (struct Node *)PermitList.mlh_Head ;
  379.             node->ln_Succ != NULL ;
  380.             node = node->ln_Succ)
  381.         {
  382.             DPrintf("\t\"%s\"\n",node->ln_Name);
  383.         }
  384.     }
  385.  
  386.     if(NOT IsListEmpty((struct List *)&ForbidList))
  387.     {
  388.         struct Node * node;
  389.  
  390.         DPrintf("\nMemory allocations done by the following task(s) are NOT being watched:\n");
  391.  
  392.         for(node = (struct Node *)ForbidList.mlh_Head ;
  393.             node->ln_Succ != NULL ;
  394.             node = node->ln_Succ)
  395.         {
  396.             DPrintf("\t\"%s\"\n",node->ln_Name);
  397.         }
  398.     }
  399.  
  400.     Permit();
  401. }
  402.